<template>
    <Tree
            :data="data"
            @on-check-change="handleCheckSelect"
            v-on="parent.$listeners"
            v-bind="parent.$attrs"
            :load-data="loadDataCallback"
            show-checkbox
    ></Tree>
</template>

<script>
    import Emitter from 'iview/src/mixins/emitter.js'

    const arrayEqual = (arr1, arr2) => {
        // 判断数组的长度
        if (arr1.length !== arr2.length) {
            return false
        } else {
            // 循环遍历数组的值进行比较
            for (let i = 0; i < arr1.length; i++) {
                if (arr1[i] !== arr2[i]) {
                    return false
                }
            }
            return true
        }
    }

    export default {
        name: 'TreeSelectTree',
        mixins: [Emitter],
        props: {
            data: {
                type: Array,
                default: () => []
            },
            selectedArray: {
                type: Array,
                default: () => []
            },
            loadData: Function
        },
        data() {
            return {
                flatDic: {},
                checkedArray: []
            }
        },
        inject: ['parent'],
        computed: {
            expandAll() {
                return this.parent.$attrs['expand-all']
            }
        },
        watch: {
            data(newData, oldVal) {
                this.vLog('oldVal', oldVal)
                this.updateFlagDic(newData)
                let selectArray = []
                this.selectedArray.forEach(id => {
                    if (id in this.flatDic) selectArray.push(id)
                })
                this.$emit('on-check', selectArray.map(id => this.flatDic[id]))
                if (this.expandAll) this.checkData(newData, false, true)
            },
            selectedArray(newVal, oldVal) {
                if (arrayEqual(newVal, oldVal)) return
                const filtedNewVal = newVal.filter(id => id in this.flatDic)
                this.$emit('on-check', filtedNewVal.map(id => this.flatDic[id]))
                this.$emit('on-clear')
                this.$nextTick(() => {
                    this.checkData(this.data, true)
                })
            }
        },
        methods: {
            checkEmit(value, label) {
                this.dispatch('iSelect', 'on-select-selected', {
                    value,
                    label
                })
                this.$emit('on-select-selected', {
                    value,
                    label
                })
            },
            updateFlagDic(newData) {
                let newFlagDic = {}
                this.setFlagDic(newData, item => {
                    newFlagDic[item.id] = item
                })
                this.flatDic = newFlagDic
            },
            setFlagDic(data, callback) {
                data.forEach(item => {
                    if (item.children && item.children.length) {
                        this.setFlagDic(item.children, callback)
                    }
                    callback(item)
                })
            },
            handleCheckSelect(selectArray, selectItem) {
                this.vLog('selectItem', selectItem)
                this.$emit('on-check', selectArray)
                this.parent.$emit('on-change', selectArray)
            },
            checkData(data, emit, expandAll) {
                data.forEach(item => {
                    if (this.selectedArray.includes(item.id)) {
                        this.$set(item, 'checked', true)
                        this.checkedArray.push(item)
                        if (emit) this.checkEmit(item.id, item.title)
                    } else this.$set(item, 'checked', false)
                    if (item.children && item.children.length) {
                        if (this.expandAll && expandAll) this.$set(item, 'expand', true)
                        this.checkData(item.children, emit, expandAll)
                    }
                })
            },
            loadDataCallback(item, callback) {
                this.loadData(item, data => {
                    return (() => {
                        callback(data)
                        this.updateFlagDic(this.data)
                    })(data)
                })
            }
        },
        mounted() {
            this.checkData(this.data, false, true)
            this.$nextTick(() => {
                this.$emit('on-check', this.checkedArray)
            })
        }
    }
</script>

<style></style>
